import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
import _pickle
import pickle
from sklearn import metrics

# 注意下面的fixmap都是二值图，也就是只有0和1

# 参考：https://blog.csdn.net/qq_40260867/article/details/90667462
def cal_CC(fixmap, salmap):
    matrix = np.corrcoef(fixmap.flatten(), salmap.flatten())
    return matrix[0][1]

# 注意最后除以的是fixmaps中为1的数量而不是size
# def cal_NSS(fixmap, salmap):
#     mu = np.mean(salmap)
#     sigma = np.std(salmap)
#     if sigma == 0:
#         return  -1
#     salmap = (salmap - mu) / sigma
#     nss = np.sum(salmap*fixmap) / np.sum(fixmap)
#     return nss

def cal_NSS(fixmap, salmap):
    prediction = salmap - np.mean(salmap)
    if np.std(salmap) == 0:
        return 1
    prediction = prediction / np.std(salmap)
    return np.mean(prediction[fixmap==1])

# 参考：https://blog.csdn.net/hfut_jf/article/details/71403741
# 如果手动计算需要归一化，这里调库的话可以不用
# call_KL(x, y) 和 cal_KL(y, x) 是不一样的
def cal_KL(fixmap, salmap):
    return stats.entropy(fixmap.flatten(), salmap.flatten())

def cal_AUC(fixmap, salmap):
    return metrics.roc_auc_score(fixmap.flatten(), salmap.flatten())


# np.seterr(all='warn')
# # example
# x = np.array([[5,45,50,70,80],[5,45,50,70,80]])
# x1 = np.array([5,45,50,70,80])
# y = np.array([[8,30,25,50,85],[8,30,25,50,85]])
# y1 = np.array([5,45,50,70,80])
# n = x.size
# print(cal_CC(x, y, n))
# # corrcoef参考：https://blog.csdn.net/qq_39514033/article/details/88931639
# print(np.corrcoef(x ,y))
# print(cal_NSS(x, y, n))
# print(cal_KL(x, y))
# print(cal_KL(x1, y1))
#
# label = [0,0,0,1]
# pred = [0.01638886, 0.06969527, 0.02103605, 0.9876039]
# print(cal_AUC(label, pred))


def unit_vector(vector):
    return vector / np.linalg.norm(vector)

def degree_distance(v1, v2):
    v1_u = unit_vector(v1)
    v2_u = unit_vector(v2)
    return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))/np.pi * 180

# 根据方向计算角度
def vector_to_ang(_v):
    # v = np.array(vector_ds[0][600][1])
    # v = np.array([0, 0, 1])
    _v = np.array(_v)
    # degree between v and [0, 1, 0]
    alpha = degree_distance(_v, [0, 1, 0])
    phi = 90.0 - alpha
    # proj1 is the projection of v onto [0, 1, 0] axis
    proj1 = [0, np.cos(alpha/180.0 * np.pi), 0]
    # proj2 is the projection of v onto the plane([1, 0, 0], [0, 0, 1])
    proj2 = _v - proj1
    # theta = degree between project vector to plane and [1, 0, 0]
    theta = degree_distance(proj2, [1, 0, 0])
    sign = -1.0 if degree_distance(_v, [0, 0, -1]) > 90 else 1.0
    theta = sign * theta
    return theta, phi

# 根据角度得到二维平面的视点坐标
def ang_to_geoxy(_theta, _phi, _h, _w):
    x = _h/2.0 - (_h/2.0) * np.sin(_phi/180.0 * np.pi)
    temp = _theta
    if temp < 0:
        temp = 180 + temp + 180
    temp = 360 - temp
    y = (temp * 1.0/360 * _w)
    return int(x), int(y)

def create_fixation_map(fixation_list, H=90, W=160):
    result = np.zeros(shape=(H, W))
    for v in fixation_list:
        theta, phi  = vector_to_ang(v)
        hi, wi = ang_to_geoxy(theta, phi, H, W)
        result[H-hi-1, W-wi-1] = 1
    return result